#!/usr/bin/env node

import { Machine } from './machine/Machine';
import { MachineMode, toU64 } from './types';
import * as fs from 'fs';
import * as path from 'path';

// 解析命令行参数
function parseArgs() {
  const args = process.argv.slice(2);
  const options: {
    file?: string;
    mode?: 'long' | 'legacy' | 'real';
    debug?: boolean;
    cycles?: number;
  } = {};

  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    switch (arg) {
      case '-f':
      case '--file':
        options.file = args[++i];
        break;
      case '-m':
      case '--mode':
        options.mode = args[++i] as 'long' | 'legacy' | 'real';
        break;
      case '-d':
      case '--debug':
        options.debug = true;
        break;
      case '-c':
      case '--cycles':
        options.cycles = parseInt(args[++i], 10);
        break;
      case '-h':
      case '--help':
        printHelp();
        process.exit(0);
      default:
        if (!options.file) {
          options.file = arg;
        } else {
          console.error(`Unknown argument: ${arg}`);
          printHelp();
          process.exit(1);
        }
    }
  }

  return options;
}

// 打印帮助信息
function printHelp() {
  console.log('Usage: blink-ts [options] [program]');
  console.log('');
  console.log('Options:');
  console.log('  -f, --file <file>    Path to the program file to execute');
  console.log('  -m, --mode <mode>    Machine mode (long|legacy|real)');
  console.log('  -d, --debug          Enable debug mode');
  console.log('  -c, --cycles <num>   Maximum number of cycles to execute');
  console.log('  -h, --help           Show this help message');
}

// 创建一个简单的测试程序（如果没有指定程序文件）
function createTestProgram(): Buffer {
  // 这是一个非常简单的测试程序，只包含几条指令
  // 实际上，应该加载编译好的ELF文件
  const program = new Uint8Array([
    0x90, // NOP
    0xB8, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RAX, 42
    0xC3  // RET
  ]);
  return Buffer.from(program);
}

// 主函数
function main() {
  const options = parseArgs();
  
  try {
    // 确定机器模式
    let mode = MachineMode.LONG;
    if (options.mode === 'legacy') {
      mode = MachineMode.LEGACY;
    } else if (options.mode === 'real') {
      mode = MachineMode.REAL;
    }
    
    // 创建虚拟机实例
    const machine = new Machine(mode);
    
    // 初始化虚拟机
    machine.initialize();
    
    // 设置最大周期数（如果指定）
    if (options.cycles) {
      machine.setMaxCycles(options.cycles);
    }
    
    // 加载程序
    let programData: Buffer;
    if (options.file) {
      // 从文件加载程序
      if (!fs.existsSync(options.file)) {
        console.error(`Program file not found: ${options.file}`);
        process.exit(1);
      }
      programData = fs.readFileSync(options.file);
    } else {
      // 创建测试程序
      console.log('No program file specified. Creating a simple test program.');
      programData = createTestProgram();
    }
    
    // 将程序加载到虚拟机内存
    machine.loadProgram(new Uint8Array(programData));
    
    if (options.debug) {
      console.log('Machine initialized. Press Enter to start execution...');
      process.stdin.once('data', () => {
        runMachine();
      });
    } else {
      runMachine();
    }
    
    function runMachine() {
      // 运行虚拟机
      console.log('Starting execution...');
      const startTime = Date.now();
      const status = machine.run();
      const endTime = Date.now();
      
      // 打印执行结果
      console.log('\nExecution completed.');
      console.log(`Status: ${status === 0 ? 'SUCCESS' : 'ERROR'}`);
      console.log(`Cycles: ${machine.getCycles()}`);
      console.log(`Time: ${endTime - startTime}ms`);
      
      // 如果是调试模式，打印详细状态
      if (options.debug) {
        machine.printState();
      }
      
      // 检查是否有错误
      const errorMessage = machine.getErrorMessage();
      if (errorMessage) {
        console.error('Error:', errorMessage);
        process.exit(1);
      }
    }
  } catch (error) {
    console.error('Error:', error instanceof Error ? error.message : String(error));
    process.exit(1);
  }
}

// 运行主函数
if (require.main === module) {
  main();
}

// 导出主要类以便在其他模块中使用
export { Machine } from './machine/Machine';
export { MachineMode } from './types';